package com.zcq.thumbup.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zcq.thumbup.constant.ThumbConstant;
import com.zcq.thumbup.manager.cache.CacheManager;
import com.zcq.thumbup.mapper.ThumbMapper;
import com.zcq.thumbup.model.dto.DoThumbRequest;
import com.zcq.thumbup.model.entity.Blog;
import com.zcq.thumbup.model.entity.Thumb;
import com.zcq.thumbup.model.entity.User;
import com.zcq.thumbup.service.ThumbService;
import com.zcq.thumbup.service.UserService;
import com.zcq.thumbup.util.RedisKeyUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * 点赞Service实现
 */
@Service("thumbServiceLocalCache")
@RequiredArgsConstructor
public class ThumbServiceImpl extends ServiceImpl<ThumbMapper, Thumb>
        implements ThumbService {

    private final UserService userService;
    private final BlogServiceImpl blogService;
    private final TransactionTemplate transactionTemplate;
    private final RedisTemplate<String, Object> redisTemplate;
    private final CacheManager cacheManager;

    @Override
    public Boolean doThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        if (doThumbRequest == null || doThumbRequest.getBlogId() == null) {
            throw new RuntimeException("参数错误");
        }
        Long blogId = doThumbRequest.getBlogId();
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new RuntimeException("未登录");
        }

        synchronized (String.valueOf(loginUser.getId()).intern()) {
            return transactionTemplate.execute(status -> {
                boolean exists = this.hasThumb(blogId, loginUser.getId());
                if (exists) {
                    throw new RuntimeException("用户已点赞");
                }
                boolean update = blogService.lambdaUpdate()
                        .eq(Blog::getId, blogId)
                        .setSql("thumbCount = thumbCount + 1")
                        .update();
                Thumb thumb = new Thumb();
                thumb.setUserId(loginUser.getId());
                thumb.setBlogId(doThumbRequest.getBlogId());
                boolean success = update && this.save(thumb);
                if (success) {
                    redisTemplate.opsForHash().put(RedisKeyUtil.getUserThumbKey(loginUser.getId()), String.valueOf(blogId), thumb.getId());
                    cacheManager.putIfPresent(RedisKeyUtil.getUserThumbKey(loginUser.getId()), String.valueOf(blogId), thumb.getId());
                }
                return success;
            });
        }
    }

    @Override
    public Boolean undoThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        if (doThumbRequest == null || doThumbRequest.getBlogId() == null) {
            throw new RuntimeException("参数错误");
        }
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new RuntimeException("未登录");
        }

        synchronized (loginUser.getId().toString().intern()) {
            // 编程式事务
            return transactionTemplate.execute(status -> {
                Long blogId = doThumbRequest.getBlogId();
                Object thumbIdObj = cacheManager.get(RedisKeyUtil.getUserThumbKey(loginUser.getId()), String.valueOf(blogId));
                if (thumbIdObj == null) {
                    throw new RuntimeException("用户未点赞");
                }
                long thumbId = Long.parseLong(String.valueOf(thumbIdObj));
                boolean update = blogService.lambdaUpdate()
                        .eq(Blog::getId, blogId)
                        .setSql("thumbCount = thumbCount - 1")
                        .update();
                boolean success = update && this.removeById(thumbId);
                if (success) {
                    redisTemplate.opsForHash().delete(RedisKeyUtil.getUserThumbKey(loginUser.getId()), String.valueOf(blogId));
                    cacheManager.putIfPresent(RedisKeyUtil.getUserThumbKey(loginUser.getId()), String.valueOf(blogId), ThumbConstant.UN_THUMB_CONSTANT);
                }
                return success;
            });
        }
    }

    @Override
    public Boolean hasThumb(Long blogId, Long userId) {
        Object thumbIdObj = cacheManager.get(RedisKeyUtil.getUserThumbKey(userId), String.valueOf(blogId));
        if (thumbIdObj == null) {
            return false;
        }
        return !ThumbConstant.UN_THUMB_CONSTANT.equals(thumbIdObj);
    }

}




